/**
 * MatrixHandler - Supporting class for XMLRPCSlave. It provides the matrix
 * multiplication functionality to the slave.
 * 
 * @author Praneeth Pulusani
 * 
 */
public class MatrixHandler {
	boolean debug1 = false;
	boolean debug2 = false;

	/**
	 * getMatrixMul- Based on the node id, calculates several result columns of
	 * the resultant matrix and returns them to the callbackhandler that was
	 * passed in from the master
	 * 
	 * @param numNodes
	 *            - number of nodes in the system.
	 * @param widthmatrix1
	 *            - width of the first square matrix
	 * @param matrix1
	 *            - the first matrix
	 * @param widthmatrix2
	 *            - width of the second matrix
	 * @param matrix2
	 *            - the second matrix
	 * @return columns of result matrix
	 */
	public Object[] getMatrixMul(int numNodes, int widthmatrix1, int[] matrix1,
			int widthmatrix2, int[] matrix2) {
		int nodeID = XMLRPCSlave.nodeID;
		// calculate how many columns to compute
		int number_of_compute_columns = widthmatrix2 / numNodes;
		if (nodeID < widthmatrix2 % numNodes) {
			number_of_compute_columns++;
		}
		if (debug1)
			System.out.println("Slave " + nodeID
					+ " started computing results for :"
					+ number_of_compute_columns + " columns");
		// Result column that gets sent back will get column id embedded in the
		// front.
		Object[] encodedResultColumns = new Object[number_of_compute_columns];
		int counter = 0;
		for (int compute_column = nodeID; compute_column < widthmatrix2; compute_column = compute_column
				+ numNodes) {
			if (debug1 && widthmatrix1 < 11)
				System.out.println("Compute column:" + compute_column);
			int[] result_column = new int[widthmatrix1 + 1];
			result_column[0] = compute_column;
			// If debug is on, print the matrices
			if (debug2) {

				System.out.println("Matrix1:");

				for (int row = 0; row < widthmatrix1; row++) {
					for (int col = 0; col < widthmatrix1; col++) {
						System.out.print(matrix1[row * widthmatrix1 + col]
								+ " ");

					}
					System.out.println();
				}

				System.out.println("Matrix2:");
				for (int row = 0; row < widthmatrix2; row++) {
					for (int col = 0; col < widthmatrix2; col++) {
						System.out.print(matrix2[row * widthmatrix2 + col]
								+ " ");

					}
					System.out.println();
				}
			}
			// Perform the resultant column computations
			for (int row = 0; row < widthmatrix1; row++) {
				result_column[row + 1] = 0;
				for (int col = 0; col < widthmatrix1; col++) {

					result_column[row + 1] += (matrix1[row * widthmatrix1 + col] * matrix2[col
							* widthmatrix2 + compute_column]);
				}
			}
			encodedResultColumns[counter] = result_column;
			counter++;
		}

		if (debug1)
			System.out.println("Slave " + nodeID
					+ " finished computing and now returning:"
					+ number_of_compute_columns + " columns");
		return encodedResultColumns;

	}
}